package graph.views.DrawingForm;

import graph.drawings.AbtractDrawing;
import graph.drawings.EdgeDrawing;
import graph.drawings.GraphDrawing;
import graph.drawings.VertexDrawing;
import graph.models.Edge;
import graph.models.Vertex;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.List;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class CanvasPanel extends JPanel implements MouseListener,
		MouseMotionListener {

	private AbtractDrawing currentDrawing;
	private GraphDrawing graphDrawing;
	private DrawingMode drawingMode;
	private int numOfVextex;

	private VertexDrawing lastVertexDrawing; // use for drawing a edge, this is
												// vertex start
	private Point lastPoint; // this is a point that we move
	private Point movingPoint; // temp point when draw edge
	private Status status; // status when drawing edge (have not finish)

	private enum Status {
		DRAWINGEDGE, IDLE
	}

	public CanvasPanel() {
		numOfVextex = 0;
		status = Status.IDLE;
		graphDrawing = new GraphDrawing();

		// this.setPreferredSize(new Dimension(900, 700));
		this.setBorder(BorderFactory.createLineBorder(Color.blue, 2));
		this.setBackground(Color.WHITE);

		this.addMouseListener(this);
		this.addMouseMotionListener(this);
	}

	public void setDrawingMode(DrawingMode drawingMode) {
		this.drawingMode = drawingMode;
		if (currentDrawing != null)
			currentDrawing.select(false);
		currentDrawing = null;
		status = Status.IDLE;
		
	}

	@Override
	public void paintComponent(Graphics graphics) {
		super.paintComponent(graphics);
		Graphics2D graphics2D = (Graphics2D) graphics;
		graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);

		if (status == Status.DRAWINGEDGE && lastVertexDrawing != null) {
			Line2D.Double line = new Line2D.Double(lastVertexDrawing
					.getPosition().getX(), lastVertexDrawing.getPosition()
					.getY(), movingPoint.x, movingPoint.y);
			graphics2D.draw(line);
		}
		graphDrawing.draw(graphics2D);
	}

	@Override
	public void mousePressed(MouseEvent e) {
		if (e.getButton() != MouseEvent.BUTTON1)
			return;

		Point point = e.getPoint();

		if (drawingMode == DrawingMode.SELECT) {
			System.out.println("Un select");
			graphDrawing.UnSelectAll();
			currentDrawing = graphDrawing.hitShape(point);
			if (currentDrawing != null) {
				System.out.println("Hit shape: " + currentDrawing.getKey());
				currentDrawing.select(true);
				lastPoint = point;
			}
		}

	}

	@Override
	public void mouseReleased(MouseEvent e) {
		if (e.getButton() != MouseEvent.BUTTON1)
			return;

		Point point = e.getPoint();
		if (drawingMode == DrawingMode.VERTEX) {
			System.out.println("mousePressed: DrawingMode.VERTEX");
			
			currentDrawing = new VertexDrawing(Integer.toString(numOfVextex),
					point);
			graphDrawing.addShape(currentDrawing);
			numOfVextex++;
			graphDrawing.UnSelectAll();
		} else if (drawingMode == DrawingMode.EDGE) {
			currentDrawing = graphDrawing.hitShape(point);
			if (currentDrawing != null
					&& currentDrawing instanceof VertexDrawing) {
				if (lastVertexDrawing == null) {
					lastVertexDrawing = (VertexDrawing) currentDrawing;
					status = Status.DRAWINGEDGE;
					movingPoint = point;
				} else {
					// there isn't a boucle
					if (!currentDrawing.getKey().equals(
							lastVertexDrawing.getKey())) {
						EdgeDrawing edge = new EdgeDrawing(lastVertexDrawing,
								(VertexDrawing) currentDrawing);

						Object response = JOptionPane
								.showInputDialog("Input value of edge (integer)");
						if (response != null) {
							int value = Integer.parseInt((String) response);
							edge.setValue(value);
						}
						graphDrawing.addShape(edge);
						lastVertexDrawing = null;
						status = Status.IDLE;

					}
				}
			}
			graphDrawing.UnSelectAll();
		} else if (drawingMode == DrawingMode.DELETE) {

		}

		repaint();

	}

	@Override
	public void mouseDragged(MouseEvent e) {
		Point point = e.getPoint();
		System.out.println("Draggin");
		if (drawingMode == DrawingMode.SELECT) {
			if (currentDrawing != null && currentDrawing.isSelected()
					&& currentDrawing instanceof VertexDrawing) {
				((VertexDrawing) currentDrawing).move(lastPoint, point);

				lastPoint = point;
				repaint();
			}
		}
	}

	@Override
	public void mouseMoved(MouseEvent e) {
		if (status == Status.DRAWINGEDGE) {
			movingPoint = e.getPoint();
		}

		repaint();
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		if (e.getButton() == MouseEvent.BUTTON3) {
			status = Status.IDLE;
			lastVertexDrawing = null;
			currentDrawing = null;
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	public GraphDrawing getGraphDrawing() {
		return this.graphDrawing;
	}
	
	public void setGraphDrawing(GraphDrawing graphDrawing) {
		this.graphDrawing = graphDrawing;
		numOfVextex = 0;
		repaint();
	}

}
